// --- 最终、完整、合并所有功能的 server.js ---
// --- 请完整复制并替换您的整个文件 ---

// 1. 模块引入
const express = require('express');
const cors = require('cors');
const path = require('path');
const fs = require('fs/promises');
const { PDFDocument, rgb, degrees } = require('pdf-lib');
const fontkit = require('@pdf-lib/fontkit');
const mongoose = require('mongoose');
const axios = require('axios');

// 2. Express 应用初始化
const app = express();
const PORT = 4000;
app.use(cors());
app.use(express.json({ limit: '10mb' }));

// 3. 数据库连接
const MONGO_URI = 'mongodb://myuser:mypassword@localhost:27017/pdf_templates?authSource=admin';
mongoose.connect(MONGO_URI)
  .then(() => console.log('成功连接到 MongoDB 数据库!'))
  .catch(err => console.error('数据库连接失败:', err));

// 4. Mongoose 数据模型 (Schema)
const elementSchema = new mongoose.Schema({
  id: { type: String, required: true },
  type: { type: String, required: true },
  x: { type: Number, required: true },
  y: { type: Number, required: true },
  width: { type: Number, required: true },
  height: { type: Number, required: true },
  // 表格特有字段
  headers: { type: [String], default: [] },
  columnWidths: { type: [Number], default: [] },
  dataKey: { type: String, default: '' },
}, { _id: true, strict: false });

const templateSchema = new mongoose.Schema({
  name: { type: String, default: '未命名模板' },
  elements: [elementSchema],
  page: {
    width: { type: Number, default: 595.28 },
    height: { type: Number, default: 841.89 },
  },
  createdAt: { type: Date, default: Date.now }
});
const Template = mongoose.model('Template', templateSchema);

// 5. 辅助函数
function replacePlaceholders(text, data) {
    if (!text) return '';
    return text.replace(/{{\s*([\w\.]+)\s*}}/g, (match, key) => {
        const keys = key.split('.');
        let value = data;
        for (const k of keys) {
            if (value && typeof value === 'object' && k in value) {
                value = value[k];
            } else { return match; }
        }
        return value !== undefined ? value : match;
    });
}

// 6. API 端点 (Endpoints)

// 保存/创建模板
app.post('/api/templates', async (req, res) => {
  try {
    const { elements, name, page } = req.body;
    if (!elements || !Array.isArray(elements)) {
      return res.status(400).send('无效的模板数据');
    }
    const newTemplate = new Template({ elements, name: name || '未命名模板', page });
    await newTemplate.save();
    res.status(201).json(newTemplate);
  } catch (error) {
    console.error('保存模板时出错:', error);
    res.status(500).send('服务器内部错误');
  }
});

// 获取模板列表
app.get('/api/templates', async (req, res) => {
  try {
    const templates = await Template.find().select('_id name createdAt').sort({ createdAt: -1 });
    res.status(200).json(templates);
  } catch (error) {
    console.error('获取模板列表时出错:', error);
    res.status(500).send('服务器内部错误');
  }
});

// 获取单个模板详情
app.get('/api/templates/:id', async (req, res) => {
  try {
    const template = await Template.findById(req.params.id);
    if (!template) return res.status(404).send('模板未找到');
    res.status(200).json(template);
  } catch (error) {
    console.error('获取单个模板时出错:', error);
    res.status(500).send('服务器内部错误');
  }
});

// 删除一个模板
app.delete('/api/templates/:id', async (req, res) => {
    try {
        const result = await Template.findByIdAndDelete(req.params.id);
        if (!result) return res.status(404).send('模板未找到');
        res.status(200).json({ message: '模板删除成功' });
    } catch (error) {
        console.error('删除模板时出错:', error);
        res.status(500).send('服务器内部错误');
    }
});

// 生成PDF
app.post('/api/generate-pdf', async (req, res) => {
  try {
    const { templateId, dynamicData } = req.body;
    if (!mongoose.Types.ObjectId.isValid(templateId)) {
      return res.status(400).send('无效的模板ID');
    }
    const templateDoc = await Template.findById(templateId);
    if (!templateDoc) {
      return res.status(404).send('模板未找到');
    }
    const templateElements = templateDoc.elements;
    const pdfDoc = await PDFDocument.create();
    pdfDoc.registerFontkit(fontkit);
    const fontPath = path.join(__dirname, 'fonts', 'PingFangSC-Regular.ttf');
    const fontBytes = await fs.readFile(fontPath);
    const customFont = await pdfDoc.embedFont(fontBytes);
    
    const pageOptions = templateDoc.page || { width: 595.28, height: 841.89 };
    let page = pdfDoc.addPage([pageOptions.width, pageOptions.height]);
    let pageHeight = page.getSize().height;
    const pageMargins = { top: 50, bottom: 50 };

    for (const element of templateElements) {
      if (element.type === 'text') {
        const text = replacePlaceholders(element.text || '', dynamicData);
        page.drawText(text, {
          x: element.x,
          y: pageHeight - element.y - (element.fontSize || 16),
          font: customFont,
          size: element.fontSize || 16,
          color: rgb(0, 0, 0),
          rotate: degrees(element.rotation || 0),
        });
      } else if (element.type === 'image' && element.src) {
        try {
          const imageResponse = await axios.get(element.src, { responseType: 'arraybuffer' });
          const imageBytes = imageResponse.data;
          let embeddedImage;
          if (element.src.toLowerCase().endsWith('.png')) {
            embeddedImage = await pdfDoc.embedPng(imageBytes);
          } else {
            embeddedImage = await pdfDoc.embedJpg(imageBytes);
          }
          page.drawImage(embeddedImage, {
            x: element.x,
            y: pageHeight - element.y - element.height,
            width: element.width,
            height: element.height,
            rotate: degrees(element.rotation || 0),
          });
        } catch (imgError) {
          // ... (图片错误处理逻辑)
        }
      } else if (element.type === 'table') {
        const tableData = dynamicData[element.dataKey] || [];
        const headers = element.headers || [];
        const colWidths = element.columnWidths || [];

        let currentY = pageHeight - element.y;
        const rowHeight = 25;
        const headerHeight = 30;

        const drawHeader = (currentPage, y) => {
            let currentX = element.x;
            currentPage.drawRectangle({ x: currentX, y: y - headerHeight, width: element.width, height: headerHeight, color: rgb(0.92, 0.92, 0.92) });
            headers.forEach((header, i) => {
                currentPage.drawText(header, { x: currentX + 5, y: y - (headerHeight/2 + 5), font: customFont, size: 12, color: rgb(0.1, 0.1, 0.1) });
                currentX += colWidths[i] || 100;
            });
        };

        // 绘制表头
        drawHeader(page, currentY);
        currentY -= headerHeight;

        // 绘制数据行
        for (const row of tableData) {
          // 检查分页
          if (currentY < rowHeight + pageMargins.bottom) {
            page = pdfDoc.addPage([pageOptions.width, pageOptions.height]);
            pageHeight = page.getSize().height;
            currentY = pageHeight - pageMargins.top;
            drawHeader(page, currentY); // 在新页面重画表头
            currentY -= headerHeight;
          }

          let currentX = element.x;
          headers.forEach((header, i) => {
            const cellText = row[header] !== undefined ? String(row[header]) : '';
            page.drawText(cellText, { x: currentX + 5, y: currentY - (rowHeight/2 + 5), font: customFont, size: 11 });
            currentX += colWidths[i] || 100;
          });
          currentY -= rowHeight;
        }
      }
    }

    const pdfBytes = await pdfDoc.save();
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', `attachment; filename="generated.pdf"`);
    res.send(Buffer.from(pdfBytes));
  } catch (error) {
    console.error('生成PDF时出错:', error);
    res.status(500).send('服务器内部错误');
  }
});

// 7. 启动服务器
app.listen(PORT, () => {
  console.log(`后端服务器正在运行在 http://localhost:${PORT}`);
});